using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using System.IO;
using System.Data;
using System.Text.RegularExpressions;
using Cyberwolf.Modules.PWCAPAdmin.Components;
using Cyberwolf.Modules.PWCAPAdmin.Configuration.DataSets;
using DotNetNuke.Services.Localization;
using Cyberwolf.AppServices.Components;

namespace Cyberwolf.Modules.PWCAPAdmin.Configuration
{
    public partial class Connection : PWCAPAdminPageBaseClass
    {
        #region Private Variables
        private const string _PK_Value =
            @"<RSAKeyValue>
        <Modulus>yruEnd5UM4RL71tup3CUtfDesrgVIO4rG1TP5ajTq6cB/5n2Jb8BL7IkwPMFt2r6Wpw9aXDB0oel2govHIhwUqiPxn3WUxzS2WHLl+Rg4IYSU8wivxlWo+QMF0zQus4jPNgUmv9LX69+xQ+18nGRpDw2Tf/3/CPnLNpueSsXRQ0=</Modulus>
        <Exponent>AQAB</Exponent>
        <P>7o8v8g7sZd4kj2hhXdEh0fuyAp/afDMrbPchjSzeVUGax2+kD15atUhVSt/RA3tIklp8XNHaA5TAtHxK6RaTGw==</P>
        <Q>2Y3OJ8RWzC38tGb/vnSnqMlVcbnvqrFl56SqPgk1hQeqy0GRGDfRvM/i+TOyweWU5vr4iRLREHAPoor5du1i9w==</Q>
        <DP>HTvAtVns0CLjugshe1yoV1IPo1CxdmzS0nyKSQGJkUsDy5K7uQJn/TUK9qzssQ+Heh/Kg5lXrP6qirN8fom8pw==</DP>
        <DQ>tnCL1J97JojeJa9GgsIzI4GLjO6fhOZ1jddyCMoSPrgaS491jPiqg4tWTSNEogPUZgtLRzAncIB5LBcdctVKKw==</DQ>
        <InverseQ>A0JPTkYyfP73zoeRQx+SCTXNSBdSloK9F+YQECx9yDFMrtQBsWpTv5fnZOiC2SaV05GUkxvLWFAL+CT7g35n0Q==</InverseQ>
        <D>MWOplUQ6wyoxzag6tvQIZqK9vlB2ZUVgnxH0bADLQIA5TmnVu7Biu5nstkz+UYbwYu65T1y2+3EsiIf+njbnFez4SbWDwXby3pv/e+EYKG8Kb9TbEkGWZMspElwKry2tJj5zTrZUYJ1OxHI/qjKs119Wo81kc1UpUlx44jWvCIk=</D>
      </RSAKeyValue>";
        private const string _ConnTemplate =
            @"server={0};database={1};uid={2};pwd={3};Min Pool Size=1;Max Pool Size=300;Pooling=true;Connection Lifetime=3000";

        private string _resourceFile;
        #endregion

        #region Public Properties
        public string LocalResourceFile
        {
            get
            {
                if (string.IsNullOrEmpty(_resourceFile))
                {
                    _resourceFile = Localization.GetResourceFile(this, "Connection");
                }
                return _resourceFile;
            }
        }

        public string OrganizationID
        {
            get { return Request["oid"]; }
        }
        #endregion

        #region Event Handlers
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                SetupUI();

                if (ErrorFlash != null) return;
                if (string.IsNullOrEmpty(OrganizationID))
                {
                    txtOrganization.ReadOnly = false;
                    txtOrganization.Enabled = true;
                    return;
                }

                try
                {
                    var responseDoc = this.AppService.GetConnectionInfo(PWSecurityToken.Current.SecurityToken);
                    var appKeys = new DSConnections();
                    using (var sr = new StringReader(responseDoc))
                    {
                        appKeys.ReadXml(sr, XmlReadMode.DiffGram);
                    }

                    var connectionRow = appKeys.PW_Connections.FirstOrDefault(r => OrganizationID.Equals(r.Organization_ID));

                    responseDoc = this.AppService.GetSymmetricKey(PWSecurityToken.Current.SecurityToken);
                    var dsSymKey = new DSSymmetricKey();
                    StringReader rdr = new StringReader(responseDoc);
                    dsSymKey.ReadXml(rdr, XmlReadMode.DiffGram);
					rdr.Close();

                    var rwSymKey = dsSymKey.ApplicationKey[0];
                    var cryptography = rwSymKey.IsSymmetricKeyNull() ? null :
                            SymmetricKey.FromString(rwSymKey.SymmetricKey, _PK_Value);

                    // Decrypt the string
                    var decryptConnect = cryptography.DecryptToString(connectionRow.Connection_Data);

                    if (string.IsNullOrEmpty(decryptConnect))
                    {
                        txtDatabaseServer.Text = txtDatabaseName.Text = txtLoginID.Text = txtPassword.Text = string.Empty;
                        return;
                    }

                    txtEnvironment.Text = connectionRow.Environment_Name;
                    txtOrganization.Text = connectionRow.Organization_ID;
                    txtLogicalName.Text = connectionRow.Logical_Name;
                    txtDataSource.Text = connectionRow.Datasource_Name;
                    txtDescription.Text = connectionRow.Description;

                    string[] connectionParts = GetConnectionParameters(decryptConnect);
                    txtDatabaseServer.Text = connectionParts[0];
                    txtDatabaseName.Text = connectionParts[1];
                    txtLoginID.Text = connectionParts[2];
                    txtPassword.Text = connectionParts[3];
                }
                catch (Exception ex)
                {
                    this.ErrorFlash = ex.Message;
                }
            }
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            var responseDoc = this.AppService.GetConnectionInfo(PWSecurityToken.Current.SecurityToken);
            var appKeys = new DSConnections();
            using (var sr = new StringReader(responseDoc))
            {
                appKeys.ReadXml(sr, XmlReadMode.DiffGram);
            }

            DSConnections.PW_ConnectionsRow connectionRow;
            if (string.IsNullOrEmpty(OrganizationID))
            {
                connectionRow = appKeys.PW_Connections.AddPW_ConnectionsRow(string.Empty, txtOrganization.Text, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty);
            }
            else
            {
                connectionRow = appKeys.PW_Connections.FirstOrDefault(r => OrganizationID.Equals(r.Organization_ID));
                connectionRow.BeginEdit();
            }

            responseDoc = this.AppService.GetSymmetricKey(PWSecurityToken.Current.SecurityToken);
            var dsSymKey = new DSSymmetricKey();
            StringReader rdr = new StringReader(responseDoc);
            dsSymKey.ReadXml(rdr, XmlReadMode.DiffGram);
            rdr.Close();

            var rwSymKey = dsSymKey.ApplicationKey[0];
            var cryptography = rwSymKey.IsSymmetricKeyNull() ? null :
                    SymmetricKey.FromString(rwSymKey.SymmetricKey, _PK_Value);

            // Build the connect string
            string connStr;
            if (string.IsNullOrEmpty(OrganizationID) || !string.IsNullOrEmpty(txtPassword.Text))
            {
                connStr = string.Format(_ConnTemplate, txtDatabaseServer.Text, txtDatabaseName.Text, txtLoginID.Text, txtPassword.Text);
            }
            else
            {
                // Decrypt the string
                var decryptConnect = cryptography.DecryptToString(connectionRow.Connection_Data);

                string[] connectionParts = GetConnectionParameters(decryptConnect);
                connStr = string.Format(_ConnTemplate, txtDatabaseServer.Text, txtDatabaseName.Text, txtLoginID.Text, connectionParts[3]);
            }

            // Encrypt the string.
            string encConn = cryptography.EncryptToString(connStr);

            connectionRow.Environment_Name = txtEnvironment.Text;
            connectionRow.Logical_Name = txtLogicalName.Text;
            connectionRow.Datasource_Name = txtDataSource.Text;
            connectionRow.Description = txtDescription.Text;
            connectionRow.Connection_Data = encConn;
            connectionRow.EndEdit();

            using (StringWriter CV = new StringWriter())
            {
                appKeys.GetChanges().WriteXml(CV, XmlWriteMode.DiffGram);
                this.AppService.UpdateConnectionInfo(PWSecurityToken.Current.SecurityToken, CV.ToString());
            }

            Page.ClientScript.RegisterStartupScript(this.GetType(), "CLOSEANDREFRESH", "window.top.DConnectionFrameModOpenClose(true);", true);
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            Literal lit = new Literal();
            lit.Text = "<link href=\"" + ResolveUrl("../module.css") + "\" type=\"text/css\" rel=\"stylesheet\" />";
            this.Header.Controls.Add(lit);

            // NoticeFlash
            if (NoticeFlash != null)
            {
                litNoticeFlash.Text = string.Format("<div class='fnotice'>{0}</div>", NoticeFlash);
                NoticeFlash = null;
            }

            // ErrorFlash
            if (ErrorFlash != null)
            {
                litErrorFlash.Text = string.Format("<div class='ferror'>{0}</div>", ErrorFlash);
                ErrorFlash = null;
            }
        }
        #endregion

        private void SetupUI()
        {
            btnSave.Text = Localization.GetString("Save.Text", LocalResourceFile);
            btnCancel.Text = Localization.GetString("Cancel.Text", LocalResourceFile);
        }

        private string[] GetConnectionParameters(string connectionString)
        {
            string[] result = new string[4];

            // Now parse into its pieces
            MatchCollection Tokens = Regex.Matches(connectionString, @"[^\=\;]+");

            // Build into parts
            for (int i = 0; i < Tokens.Count; i += 2)
            {
                if ((i + 1) >= Tokens.Count)
                {
                    // Uneven Part
                    break;
                }

                // Extract the values from the token collection
                switch (Tokens[i].Value)
                {
                    // Server name
                    case "server":
                        result[0] = Tokens[i + 1].Value;
                        break;

                    // Database name
                    case "database":
                        result[1] = Tokens[i + 1].Value;
                        break;

                    // User ID
                    case "uid":
                        result[2] = Tokens[i + 1].Value;
                        break;

                    // Password
                    case "pwd":
                        result[3] = Tokens[i + 1].Value;
                        break;
                }
            }

            return result;
        }
    }
}
